/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       scene.h
 * Author:     karooolek
 * Created on: 2009-03-10
 *
 **********************************************************************************************************************/

#ifndef SCENE_H_
#define SCENE_H_

#include "scenenode.h"
#include "../common.h"
#include "../graphics.h"
#include "../audio.h"
#include "../physics.h"

namespace mGameEngine
{
namespace Game
{

/**
 * Game scene.
 * It stores scene nodes hierarchy.
 * TODO comment on game scene
 */
class Scene
{
protected:
    /**
     * Timer.
     */
    Timer _timer;

    /**
     * Background color
     */
    Color _bgcolor;

    /**
     * Speed of sound
     */
    float _soundSpeed;

    /**
     * Doppler effect factor.
     */
    float _doppler;

    /**
     * Gravity.
     */
    Vector3 _gravity;

    /**
     * PhysX scene.
     */
    NxScene *_scene;

    /**
     * Root game scene node.
     */
    SceneNode *_root;

    /**
     * Active game scene node.
     */
    SceneNode *_active;

    /**
     * Get active game scene camera.
     * @return active game scene camera.
     */
    virtual const Graphics::Camera *_getActiveCamera() const;

    /**
     * Get active game scene microphone.
     * @return active game scene microphone.
     */
    virtual const Audio::Microphone *_getActiveMicrophone() const;

    /**
     * Set scene lights recursively.
     * @param node scene node to set lights.
     * @param light first light number to set.
     * @return last set light number.
     */
    virtual uint8 _setLights(const SceneNode *node, uint8 light = 0) const;

    /**
     * Draw scene nodes recursively.
     * @param node scene node to draw.
     */
    virtual void _drawNodes(const SceneNode *node) const;

    /**
     * Set sound sources.
     * @param node scene node to set sound sources.
     */
    virtual void _setSoundSources(const SceneNode *node) const;

    /**
     * Create scene nodes actors.
     * @param node scene node to create actors.
     */
    virtual void _createActors(SceneNode *node);

public:
    /**
     * Create empty game scene.
     */
    Scene();

    /**
     * Create new scene with specified root and active game scene nodes.
     * @param root root game scene node.
     * @param active active game scene node.
     */
    Scene(SceneNode *root, SceneNode *active = NULL);

    /**
     * Destroy game scene.
     */
    virtual ~Scene();

    /**
     * Get root game scene node.
     * @return game scene root node.
     */
    SceneNode *getRootSceneNode() const;

    /**
     * Set root game scene node.
     * @param root scene node
     */
    void setRootSceneNode(SceneNode *root);

    /**
     * Get scene background color.
     * @return scene background color
     */
    const Color &getBackgroundColor() const
    {
        return _bgcolor;
    }

    /**
     * Set scene background color.
     * @param bgcolor scene background color
     */
    void setBackgroundColor(const Color &bgcolor)
    {
        _bgcolor = bgcolor;
    }

    /**
     * Get speed of sound.
     * @return speed of sound.
     */
    float getSpeedOfSound() const
    {
        return _soundSpeed;
    }

    /**
     * Set speed of sound.
     * @param soundSpeed speed of sound.
     */
    void setSpeedOfSound(float soundSpeed)
    {
        _soundSpeed = soundSpeed;
    }

    /**
     * Get Doppler effect factor.
     * @return Doppler effect factor.
     */
    float getDopplerFactor() const
    {
        return _doppler;
    }

    /**
     * Set Doppler effect factor.
     * @param doppler Doppler effect factor. 0.0 disables effect and values
     * above 1.0 exagerate it.
     */
    void setDopplerFactor(float doppler)
    {
        _doppler = doppler;
    }

    /**
     * Get gravity.
     * @return gravity.
     */
    const Vector3 &getGravity() const
    {
        return _gravity;
    }

    /**
     * Set gravity.
     * @param gravity gravity.
     */
    void setGravity(const Vector3 &gravity)
    {
        _gravity = gravity;
    }

    /**
     * Get active game scene node.
     * @return active game scene node.
     */
    SceneNode *getActiveNode() const
    {
        return _active;
    }

    /**
     * Set scene game scene node.
     * @param active game scene node.
     */
    void setActiveNode(SceneNode *active)
    {
        _active = active;
    }

    /**
     * Scene main loop.
     */
    virtual void idle();

    /**
     * Scene update loop.
     * @param dt update time difference in seconds.
     */
    virtual void update(float dt);

    /**
     * Draw scene.
     */
    virtual void draw(void) const;
};

}
}

#endif // SCENE_H_
